package com.xs.jmb2c.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xs.jmb2c.dto.MemberBindAccountDTO;
import com.xs.jmb2c.dto.MemberRegisterDTO;
import com.xs.jmb2c.dto.MemberUpdatePasswordDTO;
import com.xs.jmb2c.entity.Member;
import com.xs.jmb2c.config.WeChatConfig;
import com.xs.jmb2c.dto.MemberLoginDTO;
import com.xs.jmb2c.exceptions.BusinessException;
import com.xs.jmb2c.handlers.BaseContextHandler;
import com.xs.jmb2c.mapper.MemberMapper;
import com.xs.jmb2c.service.MemberService;
import com.xs.jmb2c.utils.JwtUtil;
import com.xs.jmb2c.vo.MemberInfoVO;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
import java.util.HashMap;

/**
 * <p>
 * 用户信息表 服务实现类
 * </p>
 *
 * @author root
 * @since 2025-07-01
 */
@Slf4j
@Service
public class MemberServiceImpl extends ServiceImpl<MemberMapper, Member> implements MemberService {
    @Resource
    private RestTemplate restTemplate;

    @Resource
    private WeChatConfig weChatConfig;

    @Resource
    private JwtUtil jwtUtil;

    @Resource
    private HttpServletRequest request;

    @Resource
    private WxMaService wxMaService;

    @Autowired
    private BCryptPasswordEncoder passwordEncoder;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Override
    public String login(MemberLoginDTO memberLoginDTO) {
        Member member = null;
        //账号登录
        if(memberLoginDTO.getMobile() != null){
            LambdaQueryWrapper<Member> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Member::getMobile,memberLoginDTO.getMobile());
            member = this.getOne(wrapper);
            if (member == null) {
                log.info("账号不存在");
                throw new BusinessException("账号不存在或密码错误");
            }
            log.info("密码密文:{}",passwordEncoder.encode(memberLoginDTO.getPassword()));
            if(!passwordEncoder.matches(memberLoginDTO.getPassword(),member.getPassword())){           //!member.getPassword().equals(memberLoginDTO.getPassword())
                log.info("密码错误");
                throw new BusinessException("账号不存在或密码错误");
            }
        }
        else{
            // TODO 0702 微信登录
//            String url = "https://api.weixin.qq.com/sns/jscode2session?appid=<AppId>&secret=<Secret>&js_code=<Code>&grant_type=authorization_code";
//            url = url.replace("<AppId>",weChatConfig.getAppid() );
//            url = url.replace("<Secret>",weChatConfig.getSecret() );
//            url = url.replace("<Code>", memberLoginDTO.getCode());
//            //1.请求微信服务器获取openid
//            String res = restTemplate.getForObject(url, String.class);//发起http请求
//            OpenIdRes openIdRes = JSON.parseObject(res, OpenIdRes.class);
//            String openId = openIdRes.getOpenid();
//            //2.校验openid是否在数据库中
//            //构建条件？
//            LambdaQueryWrapper<Member> wrapper = new LambdaQueryWrapper<>();
//            wrapper.eq(Member::getOpenId,openId);
//            member = this.getOne(wrapper);
//
//            if(member == null){
//                // 无账户，注册
//                member = new Member();
//                member.setOpenId(openId);
//                member.setUserId(1);
//                // 注意：如果仅仅删除外键关系，不对userid进行约束或规定，系统自己填充的userId将可能超过userid定义的类型长度
//                //      这将会导致有时能够成功插入数据库，有时不能。
//                // 故这里依旧采用固定userId的方法注册
//                this.save(member);
//            }
            String openId = null;
            WxMaJscode2SessionResult sessionResult = null;
            WxMaJscode2SessionResult session = null;

            try {
                session = wxMaService.getUserService().getSessionInfo(memberLoginDTO.getCode());
            } catch (WxErrorException e) {
                throw new RuntimeException(e);
            }
            openId = session.getOpenid();

            LambdaQueryWrapper<Member> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Member::getOpenId,openId);
            member = this.getOne(wrapper);
            if(member == null){
                // 无账户，注册
                member = new Member();
                member.setOpenId(openId);
                this.save(member);
            }
        }
        //3.签发token
        HashMap<String,Object> map = new HashMap<>();
        map.put("id",member.getUserId());
        String token = jwtUtil.generateToken(map);
        return token;
    }

    @Override
    public MemberInfoVO info(){
//        String token = request.getHeader("token");
//        log.info("token:{}",token);
//        Claims claims = jwtUtil.parseToken(token);
//        Integer id = claims.get("id",Integer.class);
        Long id = BaseContextHandler.get();
        Member member = this.getById(id);
        MemberInfoVO memberInfoVO = new MemberInfoVO();
        //属性对拷
        BeanUtils.copyProperties(member,memberInfoVO);
        //隐藏部分手机号
        String mobile = member.getMobile();
        mobile = mobile.substring(0,3) + "****" + mobile.substring(7);
        memberInfoVO.setMobile(mobile);
        return memberInfoVO;
    }

    @Override
    public void updatePassword(MemberUpdatePasswordDTO memberUpdatePasswordDTO) {
//        String token = request.getHeader("Authorization");
//        log.info("token:{}",token);
//
//        if(token == null || token.equals("")){
//            throw new BusinessException("token为空");
//        }
//
//        Claims claims = jwtUtil.parseToken(token);
//        Integer id = claims.get("id",Integer.class);
        Long id = BaseContextHandler.get();
        Member member = this.getById(id);
        if(member == null){
            throw new BusinessException("用户不存在");
        }

//        member.setUserId(memberUpdatePasswordDTO.getUserId());
//        member.setPassword(memberUpdatePasswordDTO.getPassword());
//        if(memberUpdatePasswordDTO.getUserId() != null){
//            LambdaQueryWrapper<Member> wrapper = new LambdaQueryWrapper<>();
//            wrapper.eq(Member::getUserId,memberUpdatePasswordDTO.getUserId());
//            member = this.getOne(wrapper);
//            if (member == null) {
//                log.info("账号不存在");
//                throw new BusinessException("账号不存在或密码错误");
//            }
//            this.updateById(member);
//        }
        if(!passwordEncoder.matches(memberUpdatePasswordDTO.getOldPassword(),member.getPassword())){
            log.info("旧密码错误");
            throw new BusinessException("旧密码错误");
        }
        member.setPassword(passwordEncoder.encode(memberUpdatePasswordDTO.getNewPassword()));
        this.updateById(member);
    }

    @Override
    public Member register(MemberRegisterDTO memberRegisterDTO) {
        //验证码是否正确/过期
        if(!StringUtils.hasText(memberRegisterDTO.getCode())){
            throw new BusinessException("验证码为空");
        }
        if(!redisTemplate.hasKey("code")){
            throw new BusinessException("验证码已过期");
        }
        String code = redisTemplate.opsForValue().get("code");
        if(code == null){
            throw new BusinessException("验证码已过期");
        }
        if(!code.equals(memberRegisterDTO.getCode())){
            throw new BusinessException("验证码错误");
        }
        //检查手机号已注册
        //同时检查了手机号是否为空
        LambdaQueryWrapper<Member> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StringUtils.hasText(memberRegisterDTO.getMobile()), Member::getMobile, memberRegisterDTO.getMobile());
        //检查邮箱已注册
        wrapper.eq(StringUtils.hasText(memberRegisterDTO.getEmail()), Member::getEmail, memberRegisterDTO.getEmail());
        Member member = this.getOne(wrapper);
        if(member != null){
            if(StringUtils.hasText(memberRegisterDTO.getMobile())){
                throw new BusinessException("手机号已被注册");
            }
            if(StringUtils.hasText(memberRegisterDTO.getEmail())){
                throw new BusinessException("邮箱已被注册");
            }
        }
        //检查密码合法性
        if(!StringUtils.hasText(memberRegisterDTO.getPassword())){
            throw new BusinessException("密码不能为空");
        }
        member = new Member();
        member.setMobile(memberRegisterDTO.getMobile());
        member.setEmail(memberRegisterDTO.getEmail());
        member.setPassword(passwordEncoder.encode(memberRegisterDTO.getPassword()));
        this.save(member);
        //删除已使用的验证码
        redisTemplate.delete("code");
        return member;
    }

    @Override
    public void bindPhoneOrEmailOrOpenId(MemberBindAccountDTO memberBindAccountDTO) {

    }
}
